這幾天參加了幾場面試,在基礎前端知識的部分,掌握度還可以,不過遇到網路知識的部分,就會答的很吃力,所以這邊針對網路知識的部分做加強,並且記錄一下,並且希望會有幫助到有需要的人
這邊先打個預防針,因為大部分是我整理完文章的理解,所以有任何錯誤,都歡迎留言給我,謝謝
那我們廢話不多說,進主題
在講 Cookie + Session 登入前,我們應該先來了解一下,為什麼會有這兩個東西:
因為 HTTP 是一種無狀態 (stateless)
的協議,所以每次請求都是獨立的
,伺服器端無法判斷本次請求和上一次請求是否來自同一個使用者,進而也就無法判斷使用者的登入狀態。
那你可能會好奇,那為什麼要 無狀態 (stateless) 的協議
?你要想如果我們需要存儲大量的使用者狀態,就會造成很大的伺服器端維護成本,所以如果可以 客戶端、伺服器、資料庫都不去儲存使用者狀態,那不是很棒?所以 無狀態 (stateless) 的協議
就誕生了
為了解決 HTTP 無狀態帶來的問題, Lou Montulli 在 1994 年的時候,推出了 Cookie
。
Cookie
Cookie 是瀏覽器存放資料的地方,可以存放
session
之類的資料
這邊舉個網路上普遍的例子:Cookie 就是 會員卡
,瀏覽器可以透過 Cookie 去知道使用者狀態,就好像會員卡能知道你的購買記錄一樣
簡單來說,就是伺服器透過 Header
的屬性 Set-Cookie
,把使用者的狀態紀錄成儲存在使用者電腦裡的 Cookie
,而瀏覽器在每一次發送請求時,都在 Header
中設定 Cookie
屬性,把 Cookie
自動帶上,伺服器就能藉由檢視 Cookie
的內容,得知瀏覽器使用者的狀態
Cookie 雖然說是自動帶上,不過也有失效的部分,後面一點我們會提到
前面有提到 Header
能夠透過 Set-Cookie
把使用者的狀態紀錄成儲存在使用者電腦裡的 Cookie
那我們現在來看一下Set-Cookie
的內容跟一些可客製化的屬性:
Cookie
的有效 domain
(如果未設定,就會自動綁在執行 Set-Cookie 的 domain 下)Cookie
只在特定路徑下生效,未設定預設為 '/'
秒
;當數值為正數時有效,負數時為本次 Session 有效;0 為刪除 CookieSession Cookies,指的是沒有指定 Expires 或 Max-Age 的 Cookies,當瀏覽器關閉時,這些 Cookies 也會跟著消失
取得或是寫入 cookie
// 取得當前的 cookie
console.log(document.cookie)
// 寫入 cookie,myName 欄位寫入 jan
document.cookie = 'myName=jan'
// 寫入 cookie,並加入過期時間
document.cookie="myName=jan; expires=Mon, 04 Dec 2017 08:18:32 GMT; path=/"
// 寫入 cookie,設定 10 秒後失效
document.cookie="myName=jan; max-age=10; path=/"
Session
帳號登錄驗證過後,後端所發的識別證
Session
的儲存大小是與 cookie
共用,利用 session Id
來判定&記錄資料
Cookie + Session 登入
扯了這麼多,回到登入部分,使用 Cookie + Session 登入的流程大概是:
請求沒帶上 Cookie
文章中間有提到 Cookie
雖然是自動帶上的,但其實不保證一定自動帶上,以下三種狀況下,如果有任何一個條件沒有達到的話,Cookie
是不會自動帶上的:
Cookie + Session 的缺點
SessionId
,這樣會導致伺服器壓力過大。CSRF 全名為: Cross-site request forgery
,跨站請求偽造的手法就是惡意網站用釣魚手法讓你送出你已經拿到 cookie 的網站請求
這邊使用這篇文章的例子:
sessionID
)為了解決 Cookie + Session 的 CSRF 或其他諸多問題,我們可以使用 Token
的登入方式
Token 是 server 生成的一串字串,以作為 client 請求的一個令牌。當第一次登入後,server 會生成一個 Token 並返回給 client,client 後續訪問時,只需帶上這個 Token 即可完成身份認證。
Token 登入的流程大概是:
自由儲存
。Token 登入的優點
伺服器端不需要存放 Token
,所以不會對伺服器端造成壓力(是透過解析 Token 並驗證的方式執行)
Token 可以存放在前端任何地方,可以不用儲存在 Cookie 中,提升了頁面的安全性。
JWT 全名為: Json Web Token
,通常用來解決身份認證的問題,JWT 是一個很長的 base64
字串在這字串中分為三個部分別用點號來分隔: Header
, Payload
, Signature
JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties.
Header
裡面分別儲存型態和加密方法,通常系統是預設 HS256 雜湊演算法
來加密
必填欄位
非必填欄位
{
"alg": "none"
}
Payload
自定義的數據,例如: 用戶資料
具有所附特定含義的權利要求被稱為 registered claims
Signature
檢查碼是為了預防前兩部分被中間人偽照修改或利用的機制 (簽名檢查碼用),是將被轉換成 Base64
編碼的 Header、Payload 與自己定義的密鑰,透過在 Header 設定的雜湊演算法方式所產生的。
雖然 JWT 看起來是無敵了,解決了許多 Cookie + Session 的問題,不過還是有缺點:
Authentication
有變動,要讓改密碼前的 JWT 無效,這可以透過 JWT 的 exp(Expiration Time)
去解決Authorization
Header
的確能避免 CSRF
,不過因為把 JWT 放到 localStorage
中,就會衍生出 XSS 攻擊
,有心人士會將惡意的 JavaScript 程式碼載入到你的瀏覽器中,那麼 JWT 一樣會有被被盜用資源的問題,反觀 Set-Cookie
就有 HttpOnly
,可以防止 JavaScript
存取不知道各位讀者有沒有遇過公司有多個產品,但只需要登入一次,所有產品都會自動登入?這就是所謂的 SSO 單點登入
圖片取自:https://zhuanlan.zhihu.com/p/334720992SSO
流程大概是:
不同tab的cookie是共用的嗎?
由於 SSO
的作用就是能在自家產品中,登入任何一個產品後,自由切換到不同的產品,而不必在做多餘登入的動作,這時可能就會有人好奇,那存入的 cookie
是共用的嗎?其實如果兩個 tab 的 domain
, 協議
(Http or Https), port
都相同的話,cookie
就會是一樣的
OAuth 是一個開放標準的 授權協議 ,它允許 軟體應用 代表 資源擁有者 訪問資源擁有者的 資源
白話一點就是:
我們允許並授權當前的應用程式(在這是指 妳即將進入的程式,可能是 Medium 或是 twitter …)有限度的取得我們在 Facebook、Google 或其他平台的相關資訊
從標題:第三方登入,可能有些讀者已經能猜想得到這是什麼樣的登入方式了,相信各位在登入一些頁面時,會跳出一個視窗,問你要不要使用 Facebook 或是 Google 登入
上圖就是使用 OAuth ,他會詢問你是否要使用第三方(Email, Apple 帳戶)登入
OAuth 流程大概是長這樣:
這邊只是簡單的介紹一下OAuth的流程而已,如果有興趣的讀者,推薦可以讀一下這篇文章
這篇文章篇幅較長,我已經盡量再濃縮了,這邊幫大家整理一下重點:
那以上就是今天的文章,希望有幫助到大家,一樣有問題或是有錯誤都歡迎留言給我,那我們下次見,拜拜
文章同步發表到我的 Medium ,有興趣的讀者可以去看看
參考文章:
https://tw.alphacamp.co/blog/cookie-session-difference
https://blog.csdn.net/john1337/article/details/104571244
https://medium.com/pierceshih/%E7%AD%86%E8%A8%98-session-cookie-%E5%A6%82%E4%BD%95%E5%AF%A6%E8%B8%90%E4%BD%BF%E7%94%A8%E8%80%85%E8%AA%8D%E8%AD%89-4fcf3f044c54
https://jimmywei01.github.io/2019/05/14/cookie%E3%80%81session%E3%80%81local-storage%E3%80%81session-storage-%E5%B7%AE%E7%95%B0/
https://5xruby.tw/posts/hello-spa-rails-api-server
https://www.gushiciku.cn/pl/pZ8M/zh-tw
https://blog.kenwsc.com/posts/2023/jwt-vs-session/